﻿#region Header

/*
Remote views based on linq
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using InterLinq.Client;
using InterLinq.Objects;
using InterLinq.Sebarf;
using InterLinq.Server.Services.Impl;
using InterLinq.Services.Interfaces;
using InterLinq.Test.DH;
using InterLinq.Test.PD;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sebarf.Client;
using Sebarf.Configuration;
using Sebarf.Core;
using Sebarf.Core.Internal;
using Sebarf.Diagnostics.Interfaces;
using Sebarf.ProcessChains.Interfaces;
using Sebarf.Profiles.WPF;
using Sebarf.Security.UserPassword.Interfaces;
using Sebarf.Server;
using Sebarf.Services.Impl;
using Sebarf.Services.Interfaces;
using Sebastof.Server.Services.Impl;

#endregion

namespace InterLinq.Test {
	/// <summary>
	/// This class tests the security aspects of the sebarf framework
	/// </summary>
	[TestClass]
	public class TestSecurityLayer {
		#region Public Methods

		[TestMethod]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Application.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Application.xaml")]
		public void TestReadPriceNoAuthentication() {
			// create sample data
			Dictionary<Type, IList> data = SampleDataFactory.CreateInterLinqOrdersWithContent(2, 10);

			// remeber the products on the server
			IQueryable<IProduct> serverProducts = ((List<IProduct>)data[typeof(IProduct)]).AsQueryable();

			// create server query handler
			var queryHandler = new ObjectQueryHandler(new ObjectBasedDataSource(data));

			// create servermist, 
			IServer server = WcfBasedServer.Create(delegate {
				// create the base service
				var locator = new ServiceRegistrationLocatorService();
				// register backend locator service
				locator.RegisterService(new BackendProviderService());
				// register query handler locator service
				locator.RegisterService(new QueryHandlerLocatorService { QueryHandler = queryHandler });
				// create engine
				RequestHandlerEngine toReturn = RequestHandlerEngine.Create(locator,
																			 RequestHandlerLoader
																				.Load(
																				"TestSampleApplication.RequestHandler.Server.Application.xaml"),
																			 RequestHandlerLoader
																				.Load(
																				"TestSampleApplication.RequestHandler.Server.Internal.xaml"));
				// add interlinq handler
				locator.GetRegisteredService<IAddRequestHandlerService>().
					AddAddionalHandler(new ExecuteLinqQueryRequestHandler { QueryHandler = queryHandler });
				// set backend provider
				locator.GetRegisteredService<IBackendProviderRegisterService>().
					SetBackendProvider(queryHandler);

				return toReturn;
			});

			try {
				// starts the interlinq server
				server.Start();

				// create client

				// create base service
				var clientServiceLocator = new ServiceRegistrationLocatorService();

				// create engine
				IClient client = WcfBasedClient.Create("Client 1",
														RequestHandlerEngine.Create(clientServiceLocator,
																					 RequestHandlerLoader.Load(
																						"TestSampleApplication.RequestHandler.Client.Internal.xaml")));
				// connect
				client.Connect();

				// load profiles
				client.Process(new WpfBasedProfileLoadRequest("Profile", "SecurityBasedCacheBasedLazyLoadProfile_Server.xaml"));
				client.ProcessLocal(new WpfBasedProfileLoadRequest("Profile", "SecurityBasedCacheBasedLazyLoadProfile.xaml"));

				// populate remote engine
				clientServiceLocator.GetRegisteredService<IRequestRemoteHandlerEngineLocatorService>().SetRemoteEngine(client);

				// create client datacontext
				var dataContext1 =
					new SampleDataContext(
						new InterLinqQueryHandler(
							new InterLinqQueryProvider(new SebarfBasedLinqQueryGateway(clientServiceLocator, client))));
				clientServiceLocator.RegisterService(new QueryHandlerLocatorService { QueryHandler = dataContext1.QueryHandler });

				// ensure dependencies
				client.Process(new ResolveServicesDependenciesRequest());
				client.Process(new ResolveProcessChainDependenciesRequest());
				client.ProcessLocal(new ResolveServicesDependenciesRequest());
				client.ProcessLocal(new ResolveProcessChainDependenciesRequest());

				// startup services
				client.Process(new SetupServicesRequest());
				client.ProcessLocal(new SetupServicesRequest());

				// get products
				bool throwEx = false;
				try {
					IProduct[] results = dataContext1.Products.ToArray();
				}
				catch (SecurityException) {
					throwEx = true;
				}
				finally {
					Assert.IsTrue(throwEx);
				}
			}
			finally {
				server.Stop();
			}
		}

		[TestMethod]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Application.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Application.xaml")]
		public void TestReadPriceWithAuthentication() {
			// create sample data
			Dictionary<Type, IList> data = SampleDataFactory.CreateInterLinqOrdersWithContent(2, 10);

			// remeber the products on the server
			IQueryable<IProduct> serverProducts = ((List<IProduct>)data[typeof(IProduct)]).AsQueryable();

			// create server query handler
			var queryHandler = new ObjectQueryHandler(new ObjectBasedDataSource(data));

			// create server
			IServer server = WcfBasedServer.Create(delegate {
				// create the base service
				var locator = new ServiceRegistrationLocatorService();
				// register backend locator service
				locator.RegisterService(new BackendProviderService());
				// register query handler locator service
				locator.RegisterService(new QueryHandlerLocatorService { QueryHandler = queryHandler });
				// create engine
				RequestHandlerEngine toReturn = RequestHandlerEngine.Create(locator,
																			 RequestHandlerLoader
																				.Load(
																				"TestSampleApplication.RequestHandler.Server.Application.xaml"),
																			 RequestHandlerLoader
																				.Load(
																				"TestSampleApplication.RequestHandler.Server.Internal.xaml"));
				// add interlinq handler
				locator.GetRegisteredService<IAddRequestHandlerService>().
					AddAddionalHandler(new ExecuteLinqQueryRequestHandler { QueryHandler = queryHandler });
				// set backend provider
				locator.GetRegisteredService<IBackendProviderRegisterService>().
					SetBackendProvider(queryHandler);

				return toReturn;
			});

			try {
				// starts the interlinq server
				server.Start();

				// create client

				// create base service
				var clientServiceLocator = new ServiceRegistrationLocatorService();

				// create engine
				IClient client = WcfBasedClient.Create("Client 1",
														RequestHandlerEngine.Create(clientServiceLocator,
																					 RequestHandlerLoader.Load(
																						"TestSampleApplication.RequestHandler.Client.Internal.xaml")));
				// connect
				client.Connect();

				// load profiles
				client.Process(new WpfBasedProfileLoadRequest("Profile", "SecurityBasedCacheBasedLazyLoadProfile_Server.xaml"));
				client.ProcessLocal(new WpfBasedProfileLoadRequest("Profile", "SecurityBasedCacheBasedLazyLoadProfile.xaml"));

				// populate remote engine
				clientServiceLocator.GetRegisteredService<IRequestRemoteHandlerEngineLocatorService>().SetRemoteEngine(client);

				// create client datacontext
				var dataContext1 =
					new SampleDataContext(
						new InterLinqQueryHandler(
							new InterLinqQueryProvider(new SebarfBasedLinqQueryGateway(clientServiceLocator, client))));
				clientServiceLocator.RegisterService(new QueryHandlerLocatorService { QueryHandler = dataContext1.QueryHandler });

				// ensure dependencies
				client.Process(new ResolveServicesDependenciesRequest());
				client.Process(new ResolveProcessChainDependenciesRequest());
				client.ProcessLocal(new ResolveServicesDependenciesRequest());
				client.ProcessLocal(new ResolveProcessChainDependenciesRequest());

				// startup services
				client.Process(new SetupServicesRequest());
				client.ProcessLocal(new SetupServicesRequest());

				// connect

				// authentication
				clientServiceLocator.GetRegisteredService<IUsernamePasswordAuthenticationService>().Authenticate("Gfeller",
																												   "Hallo");

				// get products
				IProduct[] results = dataContext1.Products.ToArray();

				// read with authenticated user
				foreach (IProduct p in results) {
					bool throwEx = false;
					bool throwName = false;
					try {
						Logger.WriteDebug(p.Price.ToString());
					}
					catch (SecurityException) {
						throwEx = true;
					}
					try {
						Logger.WriteDebug(p.Name);
					}
					catch (SecurityException) {
						throwName = true;
					}
					Assert.IsTrue(throwEx);
					Assert.IsFalse(throwName);
				}
			}
			finally {
				server.Stop();
			}
		}

		[TestMethod]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Application.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Application.xaml")]
		public void TestReadPriceWithAuthenticationWrongPassword() {
			// create sample data
			Dictionary<Type, IList> data = SampleDataFactory.CreateInterLinqOrdersWithContent(2, 10);

			// remeber the products on the server
			IQueryable<IProduct> serverProducts = ((List<IProduct>)data[typeof(IProduct)]).AsQueryable();

			// create server query handler
			var queryHandler = new ObjectQueryHandler(new ObjectBasedDataSource(data));

			// create server
			IServer server = WcfBasedServer.Create(delegate {
				// create the base service
				var locator = new ServiceRegistrationLocatorService();
				// register backend locator service
				locator.RegisterService(new BackendProviderService());
				// register query handler locator service
				locator.RegisterService(new QueryHandlerLocatorService { QueryHandler = queryHandler });
				// create engine
				RequestHandlerEngine toReturn = RequestHandlerEngine.Create(locator,
																			 RequestHandlerLoader
																				.Load(
																				"TestSampleApplication.RequestHandler.Server.Application.xaml"),
																			 RequestHandlerLoader
																				.Load(
																				"TestSampleApplication.RequestHandler.Server.Internal.xaml"));
				// add interlinq handler
				locator.GetRegisteredService<IAddRequestHandlerService>().
					AddAddionalHandler(new ExecuteLinqQueryRequestHandler { QueryHandler = queryHandler });
				// set backend provider
				locator.GetRegisteredService<IBackendProviderRegisterService>().
					SetBackendProvider(queryHandler);

				return toReturn;
			});

			try {
				// starts the interlinq server
				server.Start();

				// create client

				// create base service
				var clientServiceLocator = new ServiceRegistrationLocatorService();

				// create engine
				IClient client = WcfBasedClient.Create("Client 1",
														RequestHandlerEngine.Create(clientServiceLocator,
																					 RequestHandlerLoader.Load(
																						"TestSampleApplication.RequestHandler.Client.Internal.xaml")));

				// connect
				client.Connect();

				// load profiles
				client.Process(new WpfBasedProfileLoadRequest("Profile", "SecurityBasedCacheBasedLazyLoadProfile_Server.xaml"));
				client.ProcessLocal(new WpfBasedProfileLoadRequest("Profile", "SecurityBasedCacheBasedLazyLoadProfile.xaml"));

				// populate remote engine
				clientServiceLocator.GetRegisteredService<IRequestRemoteHandlerEngineLocatorService>().SetRemoteEngine(client);

				// create client datacontext
				var dataContext1 =
					new SampleDataContext(
						new InterLinqQueryHandler(
							new InterLinqQueryProvider(new SebarfBasedLinqQueryGateway(clientServiceLocator, client))));
				clientServiceLocator.RegisterService(new QueryHandlerLocatorService { QueryHandler = dataContext1.QueryHandler });

				// ensure dependencies
				client.Process(new ResolveServicesDependenciesRequest());
				client.Process(new ResolveProcessChainDependenciesRequest());
				client.ProcessLocal(new ResolveServicesDependenciesRequest());
				client.ProcessLocal(new ResolveProcessChainDependenciesRequest());

				// startup services
				client.Process(new SetupServicesRequest());
				client.ProcessLocal(new SetupServicesRequest());

				// authentication with false pwd
				bool result =
					clientServiceLocator.GetRegisteredService<IUsernamePasswordAuthenticationService>().Authenticate("Gfeller",
																													   "GUGUS");
				Assert.IsFalse(result);

				// get products
				bool throwEx = false;
				try {
					IProduct[] results = dataContext1.Products.ToArray();
				}
				catch (SecurityException) {
					throwEx = true;
				}
				finally {
					Assert.IsTrue(throwEx);
				}
			}
			finally {
				server.Stop();
			}
		}

		#endregion
	}
}